#ifndef SIMP_log2_M_H
#define SIMP_log2_M_H

#include "stdint.h"
#include "rtctime.h"

#ifdef __cplusplus
extern "C"
{
#endif

	typedef struct
	{
		uint32_t blocks;
		uint32_t blocks_per_page;
		uint32_t site_start;
		uint32_t site_next;
	} simp_log2_info_type;

	typedef struct
	{
		void (*save)(void *pdat);
		void (*bits_write)(uint32_t site, void *mask, uint16_t Boffset, uint16_t BLen);
		void (*save_verify)(void *pdat);
		void (*init)(void);
		uint32_t (*site_to_addr)(uint32_t site);
		void (*read)(uint32_t site, void *pdat);
		void (*modify)(uint32_t site, uint32_t offset, void *pdat, uint16_t len);
		void (*clr)(void);
		char (*is_site_valid)(int32_t site);
		int32_t (*site_move)(int32_t site, int32_t offset);
		int32_t (*time_search)(uint32_t time, int8_t mode);
		int32_t (*flag_search)(uint8_t flag_msk, uint8_t log_flag, int32_t num, int32_t *site_des);
		int32_t (*site_iter)(int32_t s_start, int32_t s_end, int32_t (*iter_back)(int32_t site, uint8_t *dat));
		int32_t (*time_iter)(uint32_t tim_start, uint32_t tim_end, int32_t (*iter_back)(int32_t site, uint8_t *dat));
	} simp_log2_api_type;

	typedef struct
	{
		uint32_t addr_base;	 
		uint32_t total_size; 
		uint16_t page_size;	 
		uint16_t dat_size;	 
		simp_log2_info_type *info;
		void (*Erase)(uint32_t AddrBase);							 
		void (*Program)(uint32_t Addr, uint32_t *dat, uint16_t Len); 
		void (*Read)(uint32_t Addr, uint32_t *dat, uint16_t Len);	 
		const simp_log2_api_type *api;
	} simp_log2_type;

	void simp_log2_init(const simp_log2_type *cfg);
	uint32_t simp_log2_site_to_addr(const simp_log2_type *cfg, uint32_t site); 

	void simp_log2_save(const simp_log2_type *cfg, void *pdat);
	void simp_log2_save_verify(const simp_log2_type *cfg, void *pdat);
	void simp_log2_bits_write(const simp_log2_type *cfg, uint32_t site, void *mask, uint16_t Boffset, uint16_t BLen);
	void simp_log2_read(const simp_log2_type *cfg, uint32_t site, void *pdat);
	void simp_log2_clr(const simp_log2_type *cfg);

	char simp_log2_is_site_valid(const simp_log2_type *cfg, int32_t site);
	int32_t simp_log2_site_move(const simp_log2_type *cfg, int32_t site, int32_t ofsset);
	int32_t simp_log2_flag_search(const simp_log2_type *cfg, uint8_t flag_msk, uint8_t log_flag, int32_t num, int32_t *site_des); 

	void simp_log2_modify(const simp_log2_type *cfg, uint32_t site, uint32_t offset, void *pdat, uint16_t len);

	int32_t simp_log2_time_search(const simp_log2_type *cfg, uint32_t time, int8_t mode); 

	int32_t simp_log2_site_iter(
		const simp_log2_type *cfg, int32_t s_start, int32_t s_end,
		int32_t (*iter_back)(int32_t site, uint8_t *dat));

	int32_t simp_log2_time_iter(
		const simp_log2_type *cfg, uint32_t tim_start, uint32_t tim_end,
		int32_t (*iter_back)(int32_t site, uint8_t *dat));

#define simp_log2_api_make(obj)                                                                              \
                                                                                                             \
	void obj##_save(void *pdat);                                                                             \
	void obj##_bits_write(uint32_t site, void *mask, uint16_t Boffset, uint16_t BLen);                       \
	void obj##_save_verify(void *pdat);                                                                      \
	void obj##_init(void);                                                                                   \
	uint32_t obj##_site_addr(uint32_t site);                                                                 \
	void obj##_read(uint32_t site, void *pdat);                                                              \
	void obj##_modify(uint32_t site, uint32_t offset, void *pdat, uint16_t len);                             \
	void obj##_clr(void);                                                                                    \
	char obj##_is_site_valid(int32_t site);                                                                  \
	int32_t obj##_site_move(int32_t site, int32_t offset);                                                   \
	int32_t obj##_time_search(uint32_t time, int8_t mode);                                                   \
	int32_t obj##_flag_search(uint8_t flag_msk, uint8_t log_flag, int32_t num, int32_t *site_des);           \
	int32_t obj##_site_iter(int32_t s_start, int32_t s_end, int32_t (*iter_back)(int32_t, uint8_t *));       \
	int32_t obj##_time_iter(uint32_t tim_start, uint32_t tim_end, int32_t (*iter_back)(int32_t, uint8_t *)); \
                                                                                                             \
	void obj##_save(void *pdat)                                                                              \
	{                                                                                                        \
		simp_log2_save(&obj, pdat);                                                                          \
	}                                                                                                        \
	void obj##_bits_write(uint32_t site, void *mask, uint16_t Boffset, uint16_t BLen)                        \
	{                                                                                                        \
		simp_log2_bits_write(&obj, site, mask, Boffset, BLen);                                               \
	}                                                                                                        \
	void obj##_save_verify(void *pdat)                                                                       \
	{                                                                                                        \
		simp_log2_save_verify(&obj, pdat);                                                                   \
	}                                                                                                        \
	void obj##_init(void)                                                                                    \
	{                                                                                                        \
		simp_log2_init(&obj);                                                                                \
	}                                                                                                        \
	uint32_t obj##_site_addr(uint32_t site)                                                                  \
	{                                                                                                        \
		return simp_log2_site_to_addr(&obj, site);                                                           \
	}                                                                                                        \
	void obj##_read(uint32_t site, void *pdat)                                                               \
	{                                                                                                        \
		simp_log2_read(&obj, site, pdat);                                                                    \
	}                                                                                                        \
	void obj##_modify(uint32_t site, uint32_t offset, void *pdat, uint16_t len)                              \
	{                                                                                                        \
		simp_log2_modify(&obj, site, offset, pdat, len);                                                     \
	}                                                                                                        \
	void obj##_clr(void)                                                                                     \
	{                                                                                                        \
		simp_log2_clr(&obj);                                                                                 \
	}                                                                                                        \
	char obj##_is_site_valid(int32_t site)                                                                   \
	{                                                                                                        \
		return simp_log2_is_site_valid(&obj, site);                                                          \
	}                                                                                                        \
	int32_t obj##_site_move(int32_t site, int32_t offset)                                                    \
	{                                                                                                        \
		return simp_log2_site_move(&obj, site, offset);                                                      \
	}                                                                                                        \
	int32_t obj##_time_search(uint32_t time, int8_t mode)                                                    \
	{                                                                                                        \
		return simp_log2_time_search(&obj, time, mode);                                                      \
	}                                                                                                        \
	int32_t obj##_flag_search(uint8_t flag_msk, uint8_t log_flag, int32_t num, int32_t *site_des)            \
	{                                                                                                        \
		return simp_log2_flag_search(&obj, flag_msk, log_flag, num, site_des);                               \
	}                                                                                                        \
	int32_t obj##_site_iter(int32_t s_start, int32_t s_end, int32_t (*iter_back)(int32_t, uint8_t *))        \
	{                                                                                                        \
		return simp_log2_site_iter(&obj, s_start, s_end, iter_back);                                         \
	}                                                                                                        \
	int32_t obj##_time_iter(uint32_t tim_start, uint32_t tim_end, int32_t (*iter_back)(int32_t, uint8_t *))  \
	{                                                                                                        \
		return simp_log2_time_iter(&obj, tim_start, tim_end, iter_back);                                     \
	}                                                                                                        \
	const simp_log2_api_type obj##_api = {                                                                   \
		obj##_save,                                                                                          \
		obj##_bits_write,                                                                                    \
		obj##_save_verify,                                                                                   \
		obj##_init,                                                                                          \
		obj##_site_addr,                                                                                     \
		obj##_read,                                                                                          \
		obj##_modify,                                                                                        \
		obj##_clr,                                                                                           \
		obj##_is_site_valid,                                                                                 \
		obj##_site_move,                                                                                     \
		obj##_time_search,                                                                                   \
		obj##_flag_search,                                                                                   \
		obj##_site_iter,                                                                                     \
		obj##_time_iter}

#define simp_log2_api_ref(obj) extern const simp_log2_api_type obj##_api
#define simp_log2_api_name(obj) &obj##_api

#ifdef __cplusplus
}
#endif

#endif 
